<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    class LcPromise {
      constructor (executor) {
        // 成功回调列队
        this.successLists = []
        // 失败回调列队
        this.errorLists = []
        // promise状态：pending, fulfilled, rejected
        this.states = 'pending'

        executor(this.resolveFn.bind(this), this.rejectFn.bind(this))
      }

      then (onFulfilled, onRejected) {

        const {states} = this

        let promise = new LcPromise((onNextFulfilled, onNextRejected) => {
          function onFinalFufilled (val) {
            if (typeof onFulfilled !== 'function') {
              onNextFulfilled(val)
            } else {
              const res= onFulfilled(val)
              if (res && typeof res.then === 'function') {
                res.then(onNextFulfilled)
              } else {
                onNextFulfilled(res)
              }
            }
          }

          function onFinalRejected (val) {
            if (typeof onRejected !== 'function') {
              onNextRejected(val)
            } else {
              const res= onFulfilled(val)
              if (res && typeof res.then === 'function') {
                res.then(onNextRejected)
              } else {
                onNextRejected(res)
              }
            }
          }

          if (states === 'pending') {
            this.successLists.push(onFinalFufilled)
            this.errorLists.push(onFinalRejected)
          }

        })
       return promise
      }

      catch (onRejected) {
        if (typeof onRejected === 'function') {
          this.errorLists.push(onRejected)
        }
      }

      resolveFn (data) {
        setTimeout(()=>{
          this.states = 'fulfilled'
          this.successLists.forEach(item => item(data))
        })
      }

      rejectFn (err) {
        setTimeout(()=>{
          this.states = 'rejected'
          this.errorLists.forEach(item => item(err))
          throw Error(err)
        })
      }
    }

    function fn(resolve, reject) {
      setTimeout(() => {
        if (true) {
          resolve(11111)
        } else {
          reject(222)
        }
      }, 3000)
    }

    let promise = new LcPromise(fn)

    console.log(promise)

    promise.then((res) => {
      console.log('then->', res)
      return '23232'
    })
    promise.catch((err) => {
      console.log(err)
    })
  </script>
</body>
</html>